package com.igormaznitsa.elife;

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import javax.swing.JOptionPane;
import com.igormaznitsa.elife.WorldModel.Cell;

/**
 * The class describes the main form of the application
 * 
 * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com)
 * @version 1.00
 */
public class MainForm extends javax.swing.JFrame implements Runnable, ActionListener {

    private WorldModel elifeWorldModelInstance;

    /** Creates new form MainForm */
    public MainForm() {
        try {
            elifeWorldModelInstance = new WorldModel(64, 64);
        } catch (Throwable _thr) {
            _thr.printStackTrace();
            JOptionPane.showMessageDialog(null, "Fatal error [" + _thr.getMessage() + ']', "Fatal error", JOptionPane.ERROR_MESSAGE);
            System.exit(0);
        }

        initComponents();
        buttonClearAll.addActionListener(this);
        buttonAbout.addActionListener(this);
        elifeModelViewerComponent.addActionListener(this);
        elifeModelViewerComponent.setWorldModel(elifeWorldModelInstance);

        final Thread startThread = new Thread(this);
        startThread.setDaemon(true);
        startThread.start();

        setVisible(true);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    toggleButtonProcess = new javax.swing.JToggleButton();
    buttonClearAll = new javax.swing.JButton();
    delaySlider = new javax.swing.JSlider();
    elifeModelViewerComponent = new com.igormaznitsa.elife.ElifeModelViewer();
    buttonAbout = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("E-Life v.1.00");

    toggleButtonProcess.setText("Process");
    toggleButtonProcess.setToolTipText("When the button is pressed the world will be alive");

    buttonClearAll.setText("Clear all");
    buttonClearAll.setToolTipText("Clear all cells on the world field");

    delaySlider.setFont(new java.awt.Font("Arial", 0, 10)); // NOI18N
    delaySlider.setMajorTickSpacing(500);
    delaySlider.setMaximum(2000);
    delaySlider.setMinimum(100);
    delaySlider.setMinorTickSpacing(100);
    delaySlider.setPaintLabels(true);
    delaySlider.setPaintTicks(true);
    delaySlider.setSnapToTicks(true);
    delaySlider.setToolTipText("The slider allows you to choose the delay between iterations of the world life. The value of the slider in milliseconds.");
    delaySlider.setBorder(javax.swing.BorderFactory.createTitledBorder("Delay between iterations (in milliseconds)"));
    delaySlider.setRequestFocusEnabled(false);

    javax.swing.GroupLayout elifeModelViewerComponentLayout = new javax.swing.GroupLayout(elifeModelViewerComponent);
    elifeModelViewerComponent.setLayout(elifeModelViewerComponentLayout);
    elifeModelViewerComponentLayout.setHorizontalGroup(
      elifeModelViewerComponentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 412, Short.MAX_VALUE)
    );
    elifeModelViewerComponentLayout.setVerticalGroup(
      elifeModelViewerComponentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGap(0, 268, Short.MAX_VALUE)
    );

    buttonAbout.setText("About");

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addComponent(elifeModelViewerComponent, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
          .addComponent(delaySlider, javax.swing.GroupLayout.DEFAULT_SIZE, 412, Short.MAX_VALUE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
            .addComponent(toggleButtonProcess)
            .addComponent(buttonClearAll))
          .addComponent(buttonAbout))
        .addContainerGap())
    );

    layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonAbout, buttonClearAll, toggleButtonProcess});

    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(layout.createSequentialGroup()
            .addComponent(toggleButtonProcess)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(buttonClearAll)
            .addGap(47, 47, 47)
            .addComponent(buttonAbout))
          .addComponent(elifeModelViewerComponent, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(delaySlider, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap())
    );

    pack();
  }// </editor-fold>//GEN-END:initComponents
  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton buttonAbout;
  private javax.swing.JButton buttonClearAll;
  private javax.swing.JSlider delaySlider;
  private com.igormaznitsa.elife.ElifeModelViewer elifeModelViewerComponent;
  private javax.swing.JToggleButton toggleButtonProcess;
  // End of variables declaration//GEN-END:variables

    @Override
    public void run() {
        try {
            while (true) {
                if (toggleButtonProcess.isSelected()) {
                    long time = System.currentTimeMillis();
                    elifeWorldModelInstance.processIteration();
                    elifeModelViewerComponent.repaint();
                    time = System.currentTimeMillis() - time;

                    final int delayTime = delaySlider.getValue();

                    if (time < delayTime) {
                        Thread.sleep(delayTime - time);
                    }


                } else {
                    Thread.sleep(300);
                }
            }
        } catch (Throwable _thr) {
            _thr.printStackTrace();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e == null) {
            return;
        }
        final Object actionSource = e.getSource();
        if (actionSource == null) {
            return;
        }

        if (actionSource.equals(elifeModelViewerComponent)) {
            if (toggleButtonProcess.isSelected()) {
                // pressed
                toggleButtonProcess.setSelected(false);
            } else {
                // stopped
                final MouseEvent mouseEvent = elifeModelViewerComponent.getLastMouseEvent();
                if (mouseEvent == null) {
                    return;
                }
                Point p_cellcoord = elifeModelViewerComponent.coordToCell(mouseEvent.getX(), mouseEvent.getY());
                if (p_cellcoord == null) {
                    return;
                }

                boolean lg_set = mouseEvent.getButton() == MouseEvent.BUTTON1;

                Cell p_cell = elifeWorldModelInstance.getCellAt(p_cellcoord.x, p_cellcoord.y);
                if (lg_set) {
                    if (p_cell == null) {
                        elifeWorldModelInstance.createCell(p_cellcoord.x, p_cellcoord.y, 0);
                    }
                } else {
                    if (p_cell != null) {
                        elifeWorldModelInstance.removeCell(p_cell);
                    }
                }

                elifeModelViewerComponent.repaint();
            }
        } else if (actionSource.equals(buttonClearAll)) {
            if (toggleButtonProcess.isSelected()) {
                // pressed
                toggleButtonProcess.setSelected(false);
                return;
            } else if (elifeWorldModelInstance != null) {
                elifeWorldModelInstance.clearAll();
            }
            elifeModelViewerComponent.repaint();
        } else if (actionSource.equals(buttonAbout)) {
            if (toggleButtonProcess.isSelected()) {
                // pressed
                toggleButtonProcess.setSelected(false);
            }

            final AboutDialog dialog = new AboutDialog(this, true);
            dialog.setVisible(true);
        }
    }
}
